2.2 布局详解

pack 布局

使用 pack布局,将向容器中添加组件,第一个添加的组件在最上方,然后是依次向下添加。当pack布局不设置属性时,它只会占用能容纳下当前组件的最小空间

pack布局区分以下三种空间

  • 所属不明的,无人认领的空间

  • 要求但未使用的空间

  • 要求并已使用的空间

展开属性expand

“拉手效果布局”

import tkinter as tk

root = tk.Tk()

tk.Button(root, text="A").pack(side=tk.LEFT, expand=1)
tk.Button(root, text="B").pack(side=tk.LEFT, expand=1)
tk.Button(root, text="C").pack(side=tk.LEFT, expand=1)

root.mainloop()

综合示例

import tkinter as tk

root = tk.Tk()
frame = tk.Frame(root)

tk.Label(frame, text="Pack 布局的 side 和 fill").pack()
tk.Button(frame, text="A").pack(side=tk.LEFT, fill=tk.Y)
tk.Button(frame, text="B").pack(side=tk.TOP, fill=tk.X)
tk.Button(frame, text="C").pack(side=tk.RIGHT, fill=tk.NONE)
tk.Button(frame, text="D").pack(side=tk.TOP, fill=tk.BOTH)

# 需注意,顶部框架不会展开,也不会填充X或Y方向
frame.pack()

tk.Label(root, text="Pack 布局的 expand").pack()
tk.Button(root, text="我不扩展").pack()
tk.Button(root, text="我不向x方向填充,但我扩展").pack(expand=1)
tk.Button(root, text="我向x方向填充,并且扩展").pack(fill=tk.X, expand=1)

root.mainloop()

expandfill属性有什么区别? 相信绝大多数初次学习tkinter的人都会对这两个属性困惑,其实这两个属性是明显不同的,expand对应的正是要求但未使用的空间,而fill对应的是要求并已使用的空间。fill是填满的意思,将所有要求的空间占满。

pack常用属性

属性名 属性简析 取值 取值说明
fill 设置组件是否向水平或垂直方向填充 X、Y、BOTH 和NONE fill = X(水平方向填充)fill = Y(垂直方向填充)fill = BOTH(水平和垂直)NONE 不填充
expand 设置组件是否展开,当值为YES时,side选项无效。组件显示在父容器中心位置;若fill选项为BOTH,则填充父组件的剩余空间。默认为不展开 YES 、NO(1、0) expand=YES expand=NO
side 设置组件的对齐方式 LEFT、TOP、RIGHT、BOTTOM 值为左、上、右、下
ipadx、ipady 设置x方向(或者y方向)内部间隙(子组件之间的间隔) 可设置数值,默认是0 非负整数,单位为像素
padx、pady 设置x方向(或者y方向)外部间隙(与之并列的组件之间的间隔) 可设置数值,默认是0 非负整数,单位为像素
anchor 锚选项,当可用空间大于所需求的尺寸时,决定组件被放置于容器的何处 N、E、S、W、NW、NE、SW、SE、CENTER(默认值为CENTER) 表示八个方向以及中心

注意:上表中取值都是常量,YES等价于"yes",亦可以直接传入字符串值。另外当界面复杂度增加时,要实现某种布局效果,需要分层来实现。

from tkinter import *

root = Tk()

# 使用Frame增加一层容器
fm1 = Frame(root)

Button(fm1, text='Top').pack(side=TOP, anchor=W, fill=X, expand=YES)
Button(fm1, text='Center').pack(side=TOP, anchor=W, fill=X, expand=YES)
Button(fm1, text='Bottom').pack(side=TOP, anchor=W, fill=X, expand=YES)
fm1.pack(side=LEFT, fill=BOTH, expand=YES)

fm2 = Frame(root)
Button(fm2, text='Left').pack(side=LEFT)
Button(fm2, text='This is the Center button').pack(side=LEFT)
Button(fm2, text='Right').pack(side=LEFT)
fm2.pack(side=LEFT, padx=10)


root.mainloop()

pack函数

函数名 描述
pack_slaves() 以列表方式返回本组件的所有子组件对象。
pack_configure(option=value) 给pack布局管理器设置属性,使用属性(option)= 取值(value)方式设置
propagate(boolean) 设置为True表示父组件的几何大小由子组件决定(默认值),反之则无关。
pack_info() 返回pack提供的选项所对应得值。
pack_forget() Unpack组件,将组件隐藏并且忽略原有设置,对象依旧存在,可以用pack(option, …),将其显示。
location(x, y) x, y为以像素为单位的点,函数返回此点是否在单元格中,在哪个单元格中。返回单元格行列坐标,(-1, -1)表示不在其中
size() 返回组件所包含的单元格,揭示组件大小。

grid 布局

又被称作网格布局,是最被推荐使用的布局。程序大多数都是矩形的界面,我们可以很容易把它划分为一个几行几列的网格,然后根据行号和列号,将组件放置于网格之中。使用grid 布局时,需要在里面指定两个参数,分别用row 表示行,column 表示列。需要注意的是 row 和 column 的序号都从0 开始,且每个网格只能容纳一个窗口小控件。

网格布局直观感受

from tkinter import *

root = Tk()

Label(root, width=15, height=3, bg="red").grid(row=0, column=0)
Label(root, width=15, height=3, bg="green").grid(row=0, column=1)
Label(root, width=15, height=3, bg="blue").grid(row=0, column=2)
Label(root, width=15, height=3, bg="white").grid(row=1, column=0)
Label(root, width=15, height=3, bg="black").grid(row=1, column=1)
Label(root, width=15, height=3, bg="grey").grid(row=1, column=2)

root.mainloop()

使用grid布局前,要打好腹稿,将界面划分成网格状

实例

import tkinter as tk

root = tk.Tk()
tk.Label(root, text="账号").grid(row=0, sticky=tk.W)
tk.Label(root, text="密码").grid(row=1, sticky=tk.W)
tk.Entry(root).grid(row=0, column=1, sticky=tk.E)
tk.Entry(root).grid(row=1, column=1, sticky=tk.E)
tk.Button(root, text="Login").grid(row=2, column=1, sticky=tk.E)
root.mainloop()

要注意,每列的宽度(或每行的高度)由网格中小部件的高度或宽度决定。如果需要额外的设置,只能通过设置网格中的小部件的宽度实现。 另外,可以使用sticky = tk.NSEW参数使小部件可扩展并填充网格的整个单元格。

在tkinter的官方文档中,并没有给出让grid布局适配根窗口拉伸的方法,但是通过查阅tcl/Tk的文档,可知设置权重能满足该需求。

# 第一个参数是想要设置的列的序号
root.grid_columnconfigure(1, weight=1)

# 用于设置行
# root.grid_rowconfigure(1, weight=1)

grid属性设置

属性名 属性简析 取值 取值说明
row、column row为行号,column为列号,设置将组件放置于第几行第几列 取值为行、列的序号,不是行数与列数 row 和 column 的序号从0开始,但是,column的默认值是0,row的默认值是下一个编号较大的未占用行号
sticky 设置组件在网格中的对齐方式(前提是有额外的空间) N、E、S、W、NW、NE、SW、SE 类似于pack布局中的锚选项
rowspan 组件所跨越的行数 默认值为1 取值为跨越占用的行数,而不是序号
columnspan 组件所跨越的列数 默认值为1 取值为跨越占用的列数,而不是序号
ipadx、ipady、padx、pady 组件的内部、外部间隔距离,与pack的该属性用法相同 同pack 同pack

关于sticky属性,还有一些组合用法

将小控件放置在单元格的一角

  • sticky=tk.NE 右上角

  • sticky=tk.SE 右下角

  • sticky=tk.SW 左下角

  • sticky=tk.NW 左上角

拉伸小控件

  • sticky=tk.N+tk.S 垂直拉伸小控件,并保持水平居中,其等价于字符串值"ns",以下同

  • sticky=tk.E+tk.W 水平拉伸且持垂直居中

  • sticky=tk.N+tk.E+tk.S+tk.W 水平和垂直拉伸,等价于常量tk.NSEW和字符串值nsew

  • sticky=tk.N+tk.S+tk.W 将垂直拉伸并向西(左)对齐

grid函数

函数名 描述
grid_slaves() 以列表方式返回本组件的所有子组件对象。
grid_configure(option=value) 给pack布局管理器设置属性,使用属性(option)= 取值(value)方式设置
grid_propagate(boolean) 设置为True表示父组件的几何大小由子组件决定(默认值),反之则无关。
grid_info() 返回pack提供的选项所对应得值。
grid_forget() Unpack组件,将组件隐藏并且忽略原有设置,对象依旧存在,可以用pack(option, …),将其显示。
grid_location(x, y) x, y为以像素为单位的点,函数返回此点是否在单元格中,在哪个单元格中。返回单元格行列坐标,(-1, -1)表示不在其中
size() 返回组件所包含的单元格,揭示组件大小。

grid布局配合使用单元格的合并,可以设计出复杂的界面

复杂示例

import tkinter as tk

parent = tk.Tk()
parent.title('Find & Replace')

tk.Label(parent, text="Find:").grid(row=0, column=0, sticky='e')
tk.Entry(parent, width=60).grid(row=0, column=1, padx=2, pady=2, sticky='we', columnspan=9)

tk.Label(parent, text="Replace:").grid(row=1, column=0, sticky='e')
tk.Entry(parent).grid(row=1, column=1, padx=2, pady=2, sticky='we', columnspan=9)

tk.Button(parent, text="Find").grid(row=0, column=10, sticky='e' + 'w', padx=2, pady=2)
tk.Button(parent, text="Find All").grid(row=1, column=10, sticky='e' + 'w', padx=2)
tk.Button(parent, text="Replace").grid(row=2, column=10, sticky='e' + 'w', padx=2)
tk.Button(parent, text="Replace All").grid(row=3, column=10, sticky='e' + 'w', padx=2)

tk.Checkbutton(parent, text='Match whole word only ').grid(row=2, column=1, columnspan=4, sticky='w')
tk.Checkbutton(parent, text='Match Case').grid(row=3, column=1, columnspan=4, sticky='w')
tk.Checkbutton(parent, text='Wrap around').grid(row=4, column=1, columnspan=4, sticky='w')

tk.Label(parent, text="Direction:").grid(row=2, column=6, sticky='w')
tk.Radiobutton(parent, text='Up', value=1).grid(row=3, column=6, columnspan=6, sticky='w')
tk.Radiobutton(parent, text='Down', value=2).grid(row=3, column=7, columnspan=2, sticky='e')

parent.mainloop()

place 布局

place布局 最简单最灵活的一种布局,使用组件坐标来放置组件的位置。但是不太推荐使用,在不同分辨率下,界面往往有较大差异。

place属性设置

属性名 属性简析 取值 取值说明
anchor 锚选项,同pack布局 默认值为 NW 同pack布局
x、y 组件左上角的x、y坐标 整数,默认值0 绝对位置坐标,单位像素
relx、rely 组件相对于父容器的x、y坐标 0~1之间浮点数 相对位置,0.0表示左边缘(或上边缘),1.0表示右边缘(或下边缘)
width、height 组件的宽度、高度 非负整数 单位像素
relwidth、relheight 组件相对于父容器的宽度、高度 0~1之间浮点数 与relx(rely)取值相似
bordermode 如果设置为INSIDE,组件内部的大小和位置是相对的,不包括边框;如果是OUTSIDE,组件的外部大小是相对的,包括边框 INSIDE、OUTSIDE(默认值INSIDE) 可以使用常量INSIDE、OUTSIDE,也可以使用字符串形式"inside"、"outside"

place函数

函数名 描述
place_slaves() 以列表方式返回本组件的所有子组件对象。
place_configure(option=value) 给pack布局管理器设置属性,使用属性(option)= 取值(value)方式设置
propagate(boolean) 设置为True表示父组件的几何大小由子组件决定(默认值),反之则无关。
place_info() 返回pack提供的选项所对应得值。
grid_forget() Unpack组件,将组件隐藏并且忽略原有设置,对象依旧存在,可以用pack(option, …),将其显示。
location(x, y) x, y为以像素为单位的点,函数返回此点是否在单元格中,在哪个单元格中。返回单元格行列坐标,(-1, -1)表示不在其中
size() 返回组件所包含的单元格,揭示组件大小。

results matching ""

    No results matching ""